/** @file

  Copyright (C) 2022 - 2023, Phytium Technology Co., Ltd. All rights reserved.<BR>

  SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include <Protocol/PciIo.h>
#include <Library/NonDiscoverableDeviceRegistrationLib.h>
#include <Library/PhytiumSpiNorFlashLib.h>
#include <Library/FlashParTable.h>
#include <PlatformSetupVariable.h>
#include <Library/ParameterTable.h>
#include <Library/KlSetupVarRWLib.h>//[gliu-0039]
#include "PlatformDxe.h"
#include "OemConfigData.h"

typedef enum _HARDWARE_LINK_STATUS_ {
    LINK_UNAVAILABLE,
    LINK_AVAILABLE,
} EN_HARDWARE_LINK_STATUS;

/* Hardware Config For QingSong*/
struct {
    UINT8 Gmac0LinkStatus;
    UINT8 Gmac1LinkStatus;
} gstHardwareLinkConfig = {
//[jckuang-0017]
#if (FixedPcdGet8(PcdGMACxx) == 0)
    LINK_UNAVAILABLE,
    LINK_UNAVAILABLE
#elif (FixedPcdGet8(PcdGMACxx) == 1)
    LINK_AVAILABLE,
    LINK_UNAVAILABLE
#elif (FixedPcdGet8(PcdGMACxx) == 2)
    LINK_UNAVAILABLE,
    LINK_AVAILABLE
#else
    LINK_AVAILABLE,
    LINK_AVAILABLE
#endif
//[jckuang-0017]
};

STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mGmac0Desc[] = {
    {
        ACPI_ADDRESS_SPACE_DESCRIPTOR,                    // Desc
        sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3,    // Len
        ACPI_ADDRESS_SPACE_TYPE_MEM,                      // ResType
        0,                                                // GenFlag
        0,                                                // SpecificFlag
        32,                                               // AddrSpaceGranularity
        FixedPcdGet64(PcdGmac0BaseAddress),              // AddrRangeMin
        FixedPcdGet64(PcdGmac0BaseAddress) + 0x2000 - 1,     // AddrRangeMax
        0,                                                // AddrTranslationOffset
        0x2000,              // AddrLen
    }, {
        ACPI_END_TAG_DESCRIPTOR                           // Desc
    }
};

STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mGmac1Desc[] = {
    {
        ACPI_ADDRESS_SPACE_DESCRIPTOR,                    // Desc
        sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3,    // Len
        ACPI_ADDRESS_SPACE_TYPE_MEM,                      // ResType
        0,                                                // GenFlag
        0,                                                // SpecificFlag
        32,                                               // AddrSpaceGranularity
        FixedPcdGet64(PcdGmac1BaseAddress),              // AddrRangeMin
        FixedPcdGet64(PcdGmac1BaseAddress) + 0x2000 - 1,     // AddrRangeMax
        0,                                                // AddrTranslationOffset
        0x2000,              // AddrLen
    }, {
        ACPI_END_TAG_DESCRIPTOR                           // Desc
    }
};

/***********************************************************************
 * Functions        : RegisterDevice
 * Description      :
 * Input Parameters :
 * Output Parameters :
 * Return Value     :
 * Others           :
 ***********************************************************************/
STATIC
EFI_STATUS
RegisterDevice (
  IN  EFI_GUID                            *TypeGuid,
  IN  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc,
  OUT EFI_HANDLE                          *Handle
  )
{
    NON_DISCOVERABLE_DEVICE             *Device;
    EFI_STATUS                          Status;

    Device = (NON_DISCOVERABLE_DEVICE *)AllocateZeroPool(sizeof(*Device));
    if (Device == NULL) {
        return EFI_OUT_OF_RESOURCES;
    }

    Device->Type = TypeGuid;
    Device->DmaType = NonDiscoverableDeviceDmaTypeNonCoherent;
    Device->Resources = Desc;

    Status = gBS->InstallMultipleProtocolInterfaces(Handle,
             &gEdkiiNonDiscoverableDeviceProtocolGuid, Device,
             NULL);
    if (EFI_ERROR(Status)) {
        goto FreeDevice;
    }
    return EFI_SUCCESS;

FreeDevice:
    FreePool(Device);

    return Status;
}
/***********************************************************************
 * Functions        : RegisterHardwareInfo
 * Description      :
 * Input Parameters :
 * Output Parameters :
 * Return Value     :
 * Others           :
 ***********************************************************************/
void RegisterHardwareInfo()
{
  EFI_STATUS          Status;
  EFI_HANDLE          Handle;
  SYSTEM_SETUP_CONFIGURATION* SetupVar = NULL;//[gliu-0039]
  //[jckuang-0012]
  //intel NIC
  Handle = NULL;
  //
  //for intel GigUndiDxe.efi and XGigUndiDxe.efi
  //
    Status = gBS->InstallProtocolInterface (
         &Handle,
         &gIntelUndiDepexGuid,
         EFI_NATIVE_INTERFACE,
         NULL
         );
    ASSERT_EFI_ERROR (Status);
    DEBUG((EFI_D_INFO,"intel GigUndiDxe.efi and XGigUndiDxe.efi install\n"));
    //[gliu-0039]add-start
    Status = KlSetupVarRead(&SetupVar);
    if (EFI_ERROR (Status)) {
      return;
    }
    //[jckuang-0012]
    if (
      (LINK_AVAILABLE == gstHardwareLinkConfig.Gmac0LinkStatus) &&
    (SetupVar->NetController)
    ){
    //[gliu-0039]add-end
        Handle = NULL;
        Status = RegisterDevice(&gDwEmacNetNonDiscoverableDeviceGuid, mGmac0Desc, &Handle);
        ASSERT_EFI_ERROR(Status);
        DEBUG((EFI_D_INFO, "GMAC 0 install\n"));
        PcdSet64S(PcdGmac0HandleVal, (UINT64)Handle );
    }
  //[gliu-0039]add-start
    if (
       (LINK_AVAILABLE == gstHardwareLinkConfig.Gmac1LinkStatus) &&
     (SetupVar->NetController)
     ){
     //[gliu-0039]add-end
        Handle = NULL;
        Status = RegisterDevice(&gDwEmacNetNonDiscoverableDeviceGuid, mGmac1Desc, &Handle);
        ASSERT_EFI_ERROR(Status);
        DEBUG((EFI_D_INFO, "GMAC 1 install\n"));
        PcdSet64S(PcdGmac1HandleVal, (UINT64)Handle );
    }
  //[gliu-0039]add-start
    if (SetupVar != NULL) {
      FreePool(SetupVar);
    }
    return;
    //[gliu-0039]add-end
}

EFI_STATUS
OemConfigDefaultSet (
  OEM_CONFIG_DATA *OemConfigData
  )
{
  EFI_STATUS    Status;
  UINT8         Buffer[0x100];
  BOARD_CONFIG *BoardConfig;

  Status = GetParameterInfo (PM_BOARD, Buffer, sizeof (Buffer));
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "Get Board Parameter Fail.\n"));
    while (1)
      ;
  }

  BoardConfig = (BOARD_CONFIG *)Buffer;
  if (BoardConfig->PowerManger == 1) {
    OemConfigData->IsEcExisted = 1;
  } else {
    OemConfigData->IsEcExisted = 0;
  }

  OemConfigData->EnableGmac0           = 0;
  OemConfigData->EnableGmac1           = 0;
  OemConfigData->EnableUartRedirection = 1;
  OemConfigData->EnableOptee           = 0;

  return EFI_SUCCESS;
}

EFI_STATUS
OemConfigDataInit (
 VOID
 )
{
  EFI_STATUS      Status;
  OEM_CONFIG_DATA OemConfigData;
  UINTN           VarSize;

  Status                  = EFI_SUCCESS;
  VarSize                 = sizeof (OEM_CONFIG_DATA);
  Status                  = gRT->GetVariable (
                                            OEM_CONFIG_NAME,
                                            &gOemDataSetupGuid,
                                            NULL,
                                            &VarSize,
                                            &OemConfigData
                                            );

  if (EFI_ERROR (Status)) {
    if (Status == EFI_NOT_FOUND) {
      OemConfigDefaultSet (&OemConfigData);
      Status = gRT->SetVariable (
                      OEM_CONFIG_NAME,
                      &gOemDataSetupGuid,
                      PLATFORM_SETUP_VARIABLE_FLAG,
                      VarSize,
                      &OemConfigData
                      );
      ASSERT_EFI_ERROR (Status);
    } else {
      ASSERT_EFI_ERROR (Status);
    }
  }

  DEBUG ((EFI_D_INFO, "IsEcExisted = %d\n", OemConfigData.IsEcExisted));
  DEBUG ((EFI_D_INFO, "EnableGmac0 = %d\n", OemConfigData.EnableGmac0));
  DEBUG ((EFI_D_INFO, "EnableGmac1 = %d\n", OemConfigData.EnableGmac1));
  DEBUG ((EFI_D_INFO, "EnableOpte = %d\n", OemConfigData.EnableOptee));
  DEBUG ((EFI_D_INFO, "EnableUartRedirection = %d\n", OemConfigData.EnableUartRedirection));

  return Status;
}

/***********************************************************************
 * Functions        : PlatformDxeInitialise
 * Description      :
 * Input Parameters :
 * Output Parameters :
 * Return Value     :
 * Others           :
 ***********************************************************************/
EFI_STATUS
EFIAPI PlatformDxeInitialise(
    IN EFI_HANDLE         ImageHandle,
    IN EFI_SYSTEM_TABLE   *SystemTable
)
{
    OemConfigDataInit();
    RegisterHardwareInfo();
    return EFI_SUCCESS;
}

